﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.JSInterop;
using SqlSugar;
using System.Diagnostics;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using Zhao.Arena.Utility.InitDatabaseExt;
using Zhao.Common;
using Zhao.Common.Helper;
using Zhao.IServer;
using Zhao.IServer.Management_Arena;
using Zhao.IServer.User;
using Zhao.Models.DTO;
using Zhao.Models.Entity;
using Zhao.Service.User;

namespace Zhao.Arena.Controllers.User
{
    /// <summary>
    /// 管理员账户
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class AdminController : ControllerBase
    {
        private readonly IAdminServer _adminServer;
        private readonly IVenuesServer _venuesServer;
        private readonly IMemoryCache _memoryCache;
        private readonly AesGcmHelper _aesGcmHelper;
        private const string AttemptsCacheKeyFormat = "WithdrawPasswordAttempts_{0}";
        private const int MaxAttempts = 5;

        public AdminController(IAdminServer dminServer, IVenuesServer venuesServer, IMemoryCache memoryCache, AesGcmHelper aesGcmHelper)
        {
            this._adminServer = dminServer;
            this._venuesServer = venuesServer;
            this._memoryCache = memoryCache;
            this._aesGcmHelper = aesGcmHelper;
        }


        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="searchaString"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("{pageIndex:int}/{pageSize:int}")]
        [Route("{pageIndex:int}/{pageSize:int}/{searchaString}/{roleId:int}")]
        public async Task<JsonResult> GetUserPage(int pageIndex = 1, int pageSize = 10, string searchaString = " ", int roleId = 0)
        {
            Expressionable<Admin, Roles, Venues> expressionable = new Expressionable<Admin, Roles, Venues>();

            var result = new ApiResult<PageModel<AdminDto>>() { Success = false, Message = "操作失败" };

            expressionable.AndIF(!searchaString.IsNullOrWhiteSpace(), (a, b, c) => a.UserName.Contains(searchaString) || a.Phone.Contains(searchaString) || a.Email.Contains(searchaString) || a.FName.Contains(searchaString) || c.VenueName.Contains(searchaString));
            expressionable.AndIF(roleId != 0, (a, b, c) => a.Role == roleId);

            result.Data = await _adminServer.GetPageAdmin(expressionable.ToExpression(), pageIndex, pageSize);

            if (result.Data != null)
            {
                result.Success = true;
                result.Message = "操作成功";
            }

            return new JsonResult(result);
        }


        /// <summary>
        /// 创建新管理员
        /// </summary>
        [HttpPost]
        public async Task<JsonResult> CreateAdmin([FromBody] AdminAddDto dto)
        {
            var result = new ApiResult<bool> { Success = false, Message = "操作失败" };

            #region 对数据进行校验
            if (dto.isArenaAdmin)
            {
                if (dto.venueId == default || _venuesServer.QueryCount(x => x.VenueID == dto.venueId) <= 0)
                {
                    result.Message = "请选择球馆";
                    return new JsonResult(result);
                }
            }
            if (_adminServer.QueryCount(x => x.UserName.Contains(dto.uName)) > 0)
            {
                result.Message = "管理员账号已存在";
                return new JsonResult(result);
            }
            if (_adminServer.QueryCount(x => x.Phone.Contains(dto.phone)) > 0)
            {
                result.Message = "手机号码已存在";
                return new JsonResult(result);
            }
            if (_adminServer.QueryCount(x => x.Email.Contains(dto.email)) > 0)
            {
                result.Message = "邮箱已存在";
                return new JsonResult(result);
            }
            #endregion

            Admin admin = new Admin
            {
                UserName = dto.uName,
                Email = dto.email,
                Status = dto.status,
                Role = dto.role,
                CateTime = DateTime.Now,
                Password = MD5Encrypt.Encrypt(dto.newPaw),
                Phone = dto.phone,
                FName = dto.fName,
                VenueId = dto.venueId
            };

            var success = await _adminServer.AddAsync(admin) > 0;

            result.Success = success;
            result.Message = success ? "创建成功" : "创建失败";
            result.Data = success;

            return new JsonResult(result);
        }


        /// <summary>
        /// 修改管理员密码
        /// </summary>
        [HttpPut("ChangePassword")]
        public async Task<JsonResult> ChangePassword([FromBody] ChangePasswordRequest dto)
        {
            var result = new ApiResult<bool> { Success = false, Message = "操作失败" };

            string? idClaim = User?.Claims?.FirstOrDefault(c => c.Type.Equals(ClaimTypes.Sid))?.Value;

            //获取到id
            if (idClaim.IsNullOrWhiteSpace())
            {
                result.Message = "编号无效";
                return new JsonResult(result);
            }

            int id = (int)idClaim.ToInt32();

            // 1. 参数验证
            if (id <= 0)
            {
                result.Message = "管理员ID无效";
                return new JsonResult(result);
            }

            if (string.IsNullOrWhiteSpace(dto.CurrentPassword) || string.IsNullOrWhiteSpace(dto.NewPassword))
            {
                result.Message = "旧密码和新密码不能为空";
                return new JsonResult(result);
            }

            if (dto.CurrentPassword == dto.NewPassword)
            {
                result.Message = "新密码不能与旧密码相同";
                return new JsonResult(result);
            }

            // 2. 获取管理员信息
            var admin = await _adminServer.QueryAsync(id);
            if (admin == null)
            {
                result.Message = "管理员不存在";
                return new JsonResult(result);
            }

            // 3. 验证旧密码 (假设MD5Encrypt是您的加密工具类)
            var encryptedOldPwd = MD5Encrypt.Encrypt(dto.CurrentPassword);
            if (admin.Password != encryptedOldPwd)
            {
                result.Message = "旧密码不正确";
                return new JsonResult(result);
            }

            // 4. 更新密码
            admin.Password = MD5Encrypt.Encrypt(dto.NewPassword);
            admin.Updated = DateTime.Now;

            var success = await _adminServer.UpdateAsync(admin);

            // 5. 返回结果
            result.Success = success;
            result.Message = success ? "密码修改成功" : "密码修改失败";
            result.Data = success;

            return new JsonResult(result);
        }

        /// <summary>
        /// 用于查询 添加或修改管理员账号的时候 是否存在重复的账号 手机号 邮箱
        /// </summary>
        /// <param name="searchaString"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("{searchaString}")]
        [Route("{id:int}/{searchaString}")]
        public async Task<JsonResult> IsAccountExists(string searchaString, int id = 0)
        {
            var result = new ApiResult<bool> { Success = false, Message = "操作失败" };

            Expressionable<Admin> expressionable = new Expressionable<Admin>();
            //如果是修改的话就先排除自身
            expressionable.AndIF(id != 0, a => a.Id != id);
            //直接查询三个
            expressionable.And(x => x.Email.Equals(searchaString) || x.UserName.Equals(searchaString) || x.Phone.Equals(searchaString));

            result.Data = await _adminServer.QueryCountAsync(expressionable.ToExpression()) > 0;

            return new JsonResult(result);
        }


        /// <summary>
        /// 根据id删除管理员
        /// </summary>
        /// <param name="aId"></param>
        /// <returns></returns>
        [HttpDelete]
        [Route("{aId:int}")]
        public async Task<JsonResult> DelAdmin(int aId)
        {
            var result = new JsonResult(new ApiResult<Admin>() { Success = false, Message = "删除用户信息失败" });
            if (await _adminServer.DelAdmin(aId))
            {
                result = new JsonResult(new ApiResult<Admin>() { Success = true, Message = "删除用户信息" });
            }
            return await Task.FromResult(result);
        }

        /// <summary>
        /// 获取当前登录管理员的详情信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("info")]
        public async Task<JsonResult> GetByIdAdminInfo()
        {

            var result = new ApiResult<AdminDto>
            {
                Success = false,
                Message = "操作失败"
            };


            string? idClaim = User?.Claims?.FirstOrDefault(c => c.Type.Equals(ClaimTypes.Sid))?.Value;

            //获取到id

            if (idClaim.IsNullOrWhiteSpace())
            {
                result.Message = "编号无效";
                return new JsonResult(result);
            }

            int id = (int)idClaim.ToInt32();


            result.Data = await _adminServer.ByIdAdminInfo(id);

            if (result.Data != null)
            {
                result.Success = true;
                result.Message = "操作成功";
            }

            return new JsonResult(result);

        }

        /// <summary>
        /// 获取当前登录球馆管理员的详情信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("VenuInfo")]
        public async Task<JsonResult> GetByIdAdminVenuInfo()
        {

            var result = new ApiResult<AdminDto>
            {
                Success = false,
                Message = "操作失败"
            };


            string? idClaim = User?.Claims?.FirstOrDefault(c => c.Type.Equals(ClaimTypes.Sid))?.Value;

            //获取到id

            if (idClaim.IsNullOrWhiteSpace())
            {
                result.Message = "编号无效";
                return new JsonResult(result);
            }

            int id = (int)idClaim.ToInt32();

            string? venueIdClaim = User.FindFirst("VenueId").Value;

            Guid.TryParse(venueIdClaim, out Guid venueId);

            if (venueId == default)
            {
                result.Message = "无权限";
                return new JsonResult(result);
            }


            result.Data = await _adminServer.ByIdAdminVenuInfo(venueId, id);

            if (result.Data != null)
            {
                result.Success = true;
                result.Message = "操作成功";
            }

            return new JsonResult(result);

        }

        /// <summary>
        /// 管理员修改资料
        /// </summary>
        /// <param name="adminInfoDto"></param>
        /// <returns></returns>
        [HttpPut]
        public async Task<JsonResult> UpdateAdmin([FromBody] AdminInfoDto adminInfoDto)
        {
            var result = new ApiResult
            {
                Success = false,
                Message = "操作失败"
            };

            string? idClaim = User?.Claims?.FirstOrDefault(c => c.Type.Equals(ClaimTypes.Sid))?.Value;

            //获取到id

            if (idClaim.IsNullOrWhiteSpace())
            {
                result.Message = "编号无效";
                return new JsonResult(result);
            }

            adminInfoDto.Id = (int)idClaim.ToInt32();

            //账号是否重复
            if (_adminServer.QueryCount(x => x.UserName.Equals(adminInfoDto.Name) && x.Id != adminInfoDto.Id) > 0)
            {
                result.Message = "管理员账号已存在";
                return new JsonResult(result);
            }
            if (_adminServer.QueryCount(x => x.Phone.Equals(adminInfoDto.Phone) && x.Id != adminInfoDto.Id) > 0)
            {
                result.Message = "手机号码已存在";
                return new JsonResult(result);
            }
            if (_adminServer.QueryCount(x => x.Email.Equals(adminInfoDto.Email) && x.Id != adminInfoDto.Id) > 0)
            {
                result.Message = "邮箱已存在";
                return new JsonResult(result);
            }


            if (await _adminServer.UpdateIndividualInfo(adminInfoDto))
            {
                result.Message = "成功";
                result.Success = true;
            }

            return new JsonResult(result);
        }


        /// <summary>
        /// 根据密码回去当前的用户信息
        /// </summary>
        /// <param name="pwd"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("BankInfo/{pwd}")]
        public async Task<JsonResult> GetBankInfoDto(string pwd)
        {
            var result = new ApiResult<BankInfoDto>();

            var(isSuccess, message, venueId, id) =await Certification();

            var cacheKey = string.Format(AttemptsCacheKeyFormat,venueId);
            if (_memoryCache.TryGetValue(cacheKey, out int attempts) && attempts >= MaxAttempts)
            {
                result.Message = "操作过于频繁，请30分钟后再试";
                return new JsonResult(result);
            }

            //判断当前球馆交易密码是否为空 为空的话返回code让前端识别并提示用户创建
            var venuesfo = await _venuesServer.QueryAsync(x => x.VenueID == venueId && x.WithdrawPassword == pwd);

            if (venuesfo == null)
            {
                attempts = _memoryCache.GetOrCreate(cacheKey, entry =>
                {
                    entry.SlidingExpiration = TimeSpan.FromMinutes(30);
                    return 0;
                }) + 1;

                _memoryCache.Set(cacheKey, attempts, new MemoryCacheEntryOptions
                {
                    SlidingExpiration = TimeSpan.FromMinutes(15)
                });

                result.Message = attempts >= MaxAttempts
                    ? "操作过于频繁，请30分钟后再试"
                    : $"密码错误，剩余尝试次数：{MaxAttempts - attempts}";

                return new JsonResult(result);
            }
            else
            {
                if (venuesfo.BankCard.IsNullOrWhiteSpace())
                {
                    result.Success = false;
                    result.StatusCode = 409;
                    result.Message = "请绑定银行卡";
                    return new JsonResult(result);
                }

                //对银行卡进行解密
                var card = _aesGcmHelper.DecryptFromBase64(venuesfo.BankCard);

                result.Data = new BankInfoDto
                {
                    Name = venuesfo.ManagerName,
                    //替换当前银行卡
                    BankCardaccount =card.MaskBankCard(),
                    Bank = venuesfo.Bank,
                    Balance = venuesfo.Balance,
                };
                result.Success = true;
                result.Message = "成功";
                return new JsonResult(result);
            }
        }


        /// <summary>
        /// 添加客户银行卡
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("AddBankInfo")]
        public async Task<JsonResult> AddBankInfo([FromBody]BankInfoDto dto)
        {
            var result = new ApiResult();
            result.Success = false;

            // 参数校验
            if (dto.BankCardaccount.IsNullOrWhiteSpace())
            {
                result.Message = "银行卡号不能为空";
                return new JsonResult(result);
            }

            if (dto.Bank.IsNullOrWhiteSpace())
            {
                result.Message = "银行名称不能为空";
                return new JsonResult(result);
            }

            var (isSuccess, message, venueId,id) = await Certification();

            if (!isSuccess)
            {
                result.Message = message;
                return new JsonResult(result);
            }

            //对银行卡进行加密
            dto.BankCardaccount = _aesGcmHelper.EncryptToBase64(dto.BankCardaccount);

            // 构建更新实体（只更新必要字段）
            result = await _venuesServer.UpdateVenueBankInfo(venueId,dto);

            return new JsonResult(result);
        }

        /// <summary>
        /// 修改客户银行卡
        /// </summary>
        /// <param name="uBanInfnfo"></param>
        /// <returns></returns>
        [HttpPut("UpdBankInfo")]
        public async Task<JsonResult> UpdBankInfo([FromBody] UBanInfnfoDt uBanInfnfo)
        {
            var result = new ApiResult
            {
                Success = false
            };

            //对权限进行校验
            var (isSuccess, message, venueId, id) = await Certification();

            if (!isSuccess)
            {
                result.Message = message;
                return new JsonResult(result);
            }

            //密码确认
            var venues = await _venuesServer.QueryAsync(x => x.WithdrawPassword == uBanInfnfo.Password && x.VenueID== venueId);

            if (venues==null)
            {
                result.Message = "账户钱包密码不正确";
                return new JsonResult(result);
            }

            //对当前的账户卡号进行解密与当前用户输入的进行对比
            var currentCard = _aesGcmHelper.DecryptFromBase64(venues.BankCard);

            //进行比较
            if(currentCard!= uBanInfnfo.BankCardaccount)
            {
                result.Message = "当前卡号不正确";
                return new JsonResult(result);
            }

            //如果正确旧开始修改
            // 构建更新实体（只更新必要字段）
            result = await _venuesServer.UpdateVenueBankInfo(venueId, new BankInfoDto
            {
                Name=uBanInfnfo.Name,
                //加密
                BankCardaccount= _aesGcmHelper.EncryptToBase64(uBanInfnfo.NewBankCardaccount),
                Bank= uBanInfnfo.Bank
            });

            return new JsonResult(result);
        }


        /// <summary>
        /// 银行卡和钱包密码校验
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("verify")]
        public async Task<JsonResult> IsWithdrawPassword()
        {
            var result = new ApiResult
            {
                StatusCode=200,
                Success=true,
                Message="成功"
            };

            var (isSuccess, message, venueId, id) = await Certification();

            if (!isSuccess)
            {
                result.Message = message;
                return new JsonResult(result);
            }

            //查询当前是设置了钱包的密码
            var verification =await _venuesServer.QueryCountAsync(x => x.VenueID == venueId && x.WithdrawPassword != null);

            if (verification <= 0)
            {
                result.StatusCode = 400;
                result.Message = "请先设置账户密码";
                return new JsonResult(result);
            }

            //在检验是否绑定了银行卡账户
            var bankVerification = await _venuesServer.QueryCountAsync(x => x.VenueID == venueId && x.BankCard != null);

            if (verification <= 0)
            {
                result.StatusCode = 401;
                result.Message = "请先绑定银行卡账户";
                return new JsonResult(result);
            }

            return new JsonResult(result);
        }


        /// <summary>
        /// 设置用户的账户钱包密码
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("AddWithdraw")]
        public async Task<JsonResult> AddWithdraw([FromBody] ChangePasswordRequest dto)
        {
            var result = new ApiResult();

            var (isSuccess, message, venueId, id) = await Certification();

            if (!isSuccess)
            {
                result.Success = false;
                result.Message = message;
                return new JsonResult(result);
            }

            //对密码进行修改
            result = await _venuesServer.UpdateWithdrawPassword(venueId,MD5Encrypt.Encrypt(dto.NewPassword));

            return new JsonResult(result);
        }

        /// <summary>
        /// 修改用户的账户钱包密码
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("UpdWithdraw")]
        public async Task<JsonResult> UpdWithdraw([FromBody] ChangePasswordRequest dto)
        {
            var result = new ApiResult
            {
                Success=false
            };

            var (isSuccess, message, venueId, id) = await Certification();

            if (!isSuccess)
            {
                result.Message = message;
                return new JsonResult(result);
            }

            //先对旧密码进行查询
            var info = await _venuesServer.QueryAsync(v => v.VenueID == venueId && v.WithdrawPassword == dto.CurrentPassword);

            if (info == null)
            {
                result.Message = "密码错误";
                return new JsonResult(result);
            }

            //对密码进行修改
            result = await _venuesServer.UpdateWithdrawPassword(venueId, MD5Encrypt.Encrypt(dto.NewPassword));

            return new JsonResult(result);
        }


        /// <summary>
        ///验证当前管理员和球馆是否对应 返回一个元组(是否成功，msg,球馆id,当前操作人id)
        /// </summary>
        /// <returns></returns>
        private async Task<(bool IsSuccess, string Message,Guid vId,int id)> Certification()
        {
            string? idClaim = User?.Claims?.FirstOrDefault(c => c.Type.Equals(ClaimTypes.Sid))?.Value;

            //获取到id
            if (idClaim.IsNullOrWhiteSpace())
            {
                return (false, "编号无效",default,0);
            }

            int id = (int)idClaim.ToInt32();

            string? venueIdClaim = User.FindFirst("VenueId").Value;

            Guid.TryParse(venueIdClaim, out Guid venueId);

            var adminInfo = await _adminServer.QueryAsync(x => x.Id == id && x.VenueId == venueId);

            if (adminInfo == null || venueId == default)
            {
                return (false, "无权限",default,0);
            }

            return (true, "",venueId,id);
        }
    }
}
